﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProjectShare
{
    /// <summary>
    /// 经纬度
    /// </summary>
    public class LatLng
    {
        /// <summary>
        /// 经度
        /// </summary>
        public double lat { get; set; }
        /// <summary>
        /// 纬度
        /// </summary>
        public double lng { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public LatLng()
        {
            this.lat = 0;
            this.lng = 0;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="lat">纬度</param>
        /// <param name="lng">纬度</param>
        public LatLng(double lat, double lng)
        {
            this.lat = lat;
            this.lng = lng;
        }

        /// <summary>
        /// 计算两点之前的距离
        /// </summary>
        /// <param name="point">参考点</param>
        /// <returns>距离</returns>
        public double DistanceOfTwoPoints(LatLng point)
        {
            return DistanceOfTwoPoints(this, point);
        }

        /// <summary>
        /// 计算两点之前的距离
        /// </summary>
        /// <param name="point1">参考点一</param>
        /// <param name="point2">参考点二</param>
        /// <returns>距离</returns>
        public static double DistanceOfTwoPoints(LatLng point1, LatLng point2)
        {
            return DistanceOfTwoPoints(point1.lat, point1.lng, point2.lat, point2.lng);
        }

        /// <summary>
        /// 计算两点之前的距离
        /// </summary>
        /// <param name="lat1">纬度一</param>
        /// <param name="lng1">经度一</param>
        /// <param name="lat2">纬度二</param>
        /// <param name="lng2">经度二</param>
        /// <returns>距离</returns>
        public static double DistanceOfTwoPoints(double lat1, double lng1, double lat2, double lng2)
        {
            return DistanceOfTwoPoints(lat1, lng1, lat2, lng2, GaussSphere.Beijing54);
        }


        #region 私有函数

        /// <summary>
        /// 计算两点之前的距离
        /// </summary>
        /// <param name="lat1">纬度一</param>
        /// <param name="lng1">经度一</param>
        /// <param name="lat2">纬度二</param>
        /// <param name="lng2">经度二</param>
        /// <param name="gs">参考椭球</param>
        /// <returns>距离</returns>
        private static double DistanceOfTwoPoints(double lat1, double lng1, double lat2, double lng2, GaussSphere gs)
        {
            double radLat1 = Rad(lat1);
            double radLat2 = Rad(lat2);
            double a = radLat1 - radLat2;
            double b = Rad(lng1) - Rad(lng2);
            double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) +
             Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2)));
            s = s * (gs == GaussSphere.WGS84 ? 6378137.0 : (gs == GaussSphere.Xian80 ? 6378140.0 : 6378245.0));
            s = Math.Round(s * 10000) / 10000;
            return s;
        }

        /// <summary>
        /// 距离计算辅助函数
        /// </summary>
        private static double Rad(double d)
        {
            return d * Math.PI / 180.0;
        }

        /// <summary>
        /// 高斯投影中所选用的参考椭球
        /// </summary>
        private enum GaussSphere
        {
            Beijing54,
            Xian80,
            WGS84,
        }

        #endregion
    }
}
